06. ROS Services
ROS Services
Now that you've written your first ROS node, you've seen how publishing to a topic works, and you were able control the robotic arm by publishing to the
/simple_arm/joint_2_position_controller/command
topic. Next up, we'll see another node called
arm_mover
which implements the
safe_move
service to allow the arm to be controlled with service calls.
Defining services
A ROS service allows request/response communication to exist between nodes. Within the node providing the service, request messages are handled by functions or methods. Once the requests have been handled successfully, the node providing the service sends a message back to the requester node. In Python, a ROS service can be created using the following definition format:
service = rospy.Service('service_name', serviceClassName, handler)
Here, the
service_name
is the name given to the service. Other nodes will use this name to specify which service they are sending requests to.
The
serviceClassName
comes from the file name where the service definition exists. You will see more about this in the next classroom concept, but each service has a definition provided in an
.srv
file; this is a text file that provides the proper message type for both requests and responses.
The
handler
is the name of the function or method that handles the incoming service message. This function is called each time the service is called, and the message from the service call is passed to the
handler
as an argument. The
handler
should return an appropriate service response message.
Using Services
Services can be called directly from the command line, and you will see an example of this in the upcoming
arm_mover
classroom concepts.
On the other hand, to use a ROS service from within another node, you will define a
ServiceProxy
, which provides the interface for sending messages to the service:
service_proxy = rospy.ServiceProxy('service_name', serviceClassName)
One way the
ServiceProxy
can then be used to send requests is as follows:
msg = serviceClassNameRequest()
#update msg attributes here to have correct data
response = service_proxy(msg)
In the code above, a new service message is created by calling the
serviceClassNameRequest()
method. This method is provided by rospy, and its name is given by appending
Request()
to the name used for
serviceClassName
. Since the message is new, the message attributes should be updated to have the appropriate data. Next, the
service_proxy
can be called with the message, and the response stored.
For other ways to pass data to
service_proxy
, see the ROS documentation
here
.
Services quiz
SOLUTION:
- A node for a lunar rover that shuts down a robotic arm by folding the arm and killing all related processes.
- A node that sets a given parameter on request. For example, a node in turtlesim that sets the pen color in the turtlesim window.
- A node which executes movement for a robotic arm, checking that the arm joints are within specified bounds.
Let's get started with the
arm_mover
code, so you can see how to combine the
safe_move
service along with publishers in a node!